package com.bsg.upm.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.OrderCheck;
import com.bsg.upm.constant.DictConstants;
import com.bsg.upm.constant.DictTypeConstants;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.constant.SubTaskDictConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.constant.TaskDictConstants;
import com.bsg.upm.dto.OrderDto;
import com.bsg.upm.dto.SubOrderDto;
import com.bsg.upm.entity.AreaEntity;
import com.bsg.upm.entity.BusinessSubSystemEntity;
import com.bsg.upm.entity.BusinessSystemEntity;
import com.bsg.upm.entity.ClusterEntity;
import com.bsg.upm.entity.DefinitionServEntity;
import com.bsg.upm.entity.DefinitionSubServArchEntity;
import com.bsg.upm.entity.DefinitionSubServEntity;
import com.bsg.upm.entity.DefinitionSubServUnitScaleEntity;
import com.bsg.upm.entity.DefinitionSubTaskConfigEntity;
import com.bsg.upm.entity.NetworkingEntity;
import com.bsg.upm.entity.OperateLogEntity;
import com.bsg.upm.entity.OrderEntity;
import com.bsg.upm.entity.PortEntity;
import com.bsg.upm.entity.ServEntity;
import com.bsg.upm.entity.SiteEntity;
import com.bsg.upm.entity.SubOrderEntity;
import com.bsg.upm.entity.SubServEntity;
import com.bsg.upm.entity.SubServSoftwareImageEntity;
import com.bsg.upm.entity.SubTaskEntity;
import com.bsg.upm.entity.TaskEntity;
import com.bsg.upm.entity.UnitEntity;
import com.bsg.upm.entity.UserEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.HttpClientUtils;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;
import com.bsg.upm.util.BeanUtils;
import com.bsg.upm.util.DateUtils;
import com.bsg.upm.util.PrimaryKeyUtils;

/**
 * 工单管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class OrderService extends BaseService {

	@Resource
	private OrderCheck orderCheck;

	/**
	 * 获取工单列表
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常
	 */
	public RespJson list(Map<String, Object> paramMap) throws APIException {
		try {
			JSONArray retJsonArray = new JSONArray();

			// 获取指定条件的工单(指定站点和工单类型，其他过滤条件通过逻辑过滤，目的：减少SQL查询次数，因为需要查工单关联的变更工单)
			List<OrderEntity> orders = orderDao.list(paramMap);
			if (orders != null) {
				for (OrderEntity order : orders) {
					// 工单状态过滤
					if (paramMap.containsKey("status")) {
						String status = (String) paramMap.get("status");
						if (StringUtils.isNotBlank(status)) {
							if (!order.getStatus().equals(status)) {
								continue;
							}
						}
					}

					// 工单类型过滤
					if (paramMap.containsKey("type")) {
						String type = (String) paramMap.get("type");
						if (StringUtils.isNotBlank(type)) {
							List<String> types = Arrays.asList(type.split(","));
							if (!types.contains(order.getType())) {
								continue;
							}
						}
					}

					// 构建工单展示对象
					OrderDto orderDto = buildShowDto(order, false);

					// 获取关联工单
					OrderEntity associateOrder = getAssociateOrder(orders, order);
					if (associateOrder != null) {
						OrderDto associateOrderDto = buildShowDto(associateOrder, false);
						orderDto.setAssociateOrder(associateOrderDto);
					}
					retJsonArray.add(orderDto);
				}
			}

			return RespJsonFactory.buildOK(retJsonArray);
		} catch (Exception e) {
			logger.error("工单查询异常", e);
			throw new APIException("工单查询异常:" + e.getMessage());
		}
	}

	/**
	 * 获取工单
	 * 
	 * @param orderId
	 *            工单编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson get(String orderId) throws APIException {
		try {
			// 获取指定的工单
			OrderEntity order = orderDao.get(orderId);
			if (order == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "该工单不存在");
			}

			// 构建工单展示对象
			OrderDto orderDto = buildShowDto(order, true);
			if (StringUtils.isNotBlank(order.getAssociateOrderId())) {
				// 获取关联的变更工单
				OrderEntity associateOrder = orderDao.get(order.getAssociateOrderId());

				if (associateOrder != null) {
					OrderDto associateOrderDto = buildShowDto(associateOrder, true);
					orderDto.setAssociateOrder(associateOrderDto);
				}
			}

			return RespJsonFactory.buildOK(orderDto);
		} catch (Exception e) {
			logger.error("工单获取异常", e);
			throw new APIException("工单获取异常:" + e.getMessage());
		}
	}

	/**
	 * 工单克隆
	 * 
	 * @param orderId
	 *            工单编码
	 * @param cnt
	 *            克隆数量
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson clone(String orderId, Integer cnt) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_CLONE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			OrderEntity order = orderDao.get(orderId);
			CheckResult chkRS = orderCheck.checkClone(order);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			int maxNo = orderDao.getMaxNoBySiteIdAndServName(order.getArea().getSite().getId(), order.getServName());
			List<OrderEntity> newOrders = new ArrayList<>();
			for (int i = 0; i < cnt; i++) {
				OrderEntity newOrder = (OrderEntity) BeanUtils.clone(order);
				newOrder.setId(PrimaryKeyUtils.uniqueId());
				// 工单类型
				newOrder.setType(DictConstants.ORDER_TYPE_CREATE);
				// 工单状态
				newOrder.setStatus(DictConstants.ORDER_STATUS_UNAPPROVED);
				newOrder.setNo(maxNo + i + 1);
				newOrder.setAssociateOrderId(null);

				List<SubOrderEntity> newSubOrders = newOrder.getSubOrders();
				for (SubOrderEntity newSubOrder : newSubOrders) {
					newSubOrder.setId(PrimaryKeyUtils.uniqueId());
					newSubOrder.setOrder(null);
				}
				newOrders.add(newOrder);
				saveOrderDetail(newOrder);
			}

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(OperateDictConstants.MODEL_ORDER, operateAcion, order.getId(),
					order.getServName(), order.getCreateDateTime());

			// 是否自动审批
			boolean autoApprove = isAutoApprove();
			if (!autoApprove) {
				txManager.commit(txStatus);
				return RespJsonFactory.buildCreated();
			}

			List<TaskEntity> tasks = new ArrayList<>();
			for (OrderEntity newOrder : newOrders) {
				// 设置工单状态为已执行
				newOrder.setStatus(DictConstants.ORDER_STATUS_EXECUTED);
				orderDao.updateStatusAndMsg(newOrder);

				// 构建服务对象
				ServEntity serv = buildServ(newOrder, newOrder.getCreateDateTime());
				saveServDetail(serv);

				// 构建服务创建任务
				TaskEntity task = buildCreateServTask(serv, operateLog);
				tasks.add(task);
				saveTask(task);
			}

			txManager.commit(txStatus);
			for (TaskEntity task : tasks) {
				startTask(task);
			}

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 工单新增
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_ADD;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 新增检查
			CheckResult chkRS = orderCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			// 构建工单对象
			OrderEntity order = buildOrder(paramMap);
			saveOrderDetail(order);

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(OperateDictConstants.MODEL_ORDER, operateAcion, order.getId(),
					order.getServName(), order.getCreateDateTime());

			// 是否自动审批
			boolean autoApprove = isAutoApprove();
			if (!autoApprove) {
				txManager.commit(txStatus);
				return RespJsonFactory.buildCreated();
			}

			// 获取指定的工单信息
			order = orderDao.get(order.getId());

			// 设置工单状态为已执行
			order.setStatus(DictConstants.ORDER_STATUS_EXECUTED);
			orderDao.updateStatusAndMsg(order);

			// 构建服务对象
			ServEntity serv = buildServ(order, order.getCreateDateTime());
			saveServDetail(serv);

			// 构建服务创建任务
			TaskEntity task = buildCreateServTask(serv, operateLog);
			saveTask(task);
			txManager.commit(txStatus);

			startTask(task);
			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 工单编辑
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson update(Map<String, Object> paramMap) throws APIException {
		String operateAcion = OperateDictConstants.ACTION_UPDATE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// check
			// CheckResult chkRS = orderCheck.checkUpdate(paramMap);
			// if (chkRS.isError()) {
			// return RespJsonFactory.build(chkRS.getStatus(),
			// chkRS.getErrorMsg());
			// }

			OrderEntity order = buildOrderToUpdate(paramMap);
			updateOrderDetail(order);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_ORDER, operateAcion, order.getId(), order.getServName());

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 工单审批
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson approve(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_APPROVE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			String orderId = (String) paramMap.get("orderId");
			// 获取指定的工单
			OrderEntity order = orderDao.get(orderId);

			// 工单审批检查
			CheckResult chkRS = orderCheck.checkAudit(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			order.setStatus((String) paramMap.get("status"));
			order.setMsg((String) paramMap.get("msg"));
			orderDao.updateStatusAndMsg(order);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_ORDER, operateAcion, order.getId(), order.getServName());

			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 工单执行
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson execute(Map<String, Object> paramMap) throws APIException {
		// 事务定义
		DefaultTransactionDefinition def = null;
		// 事务状态
		TransactionStatus txStatus = null;

		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_EXECUTE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// String orderId = (String) paramMap.get("orderId");
			//
			// // 获取工单信息
			// OrderEntity order = orderDao.get(orderId);
			//
			// // 工单检查
			// CheckResult chkRS = orderCheck.checkExecute(order);
			// if (chkRS.isError()) {
			// return RespJsonFactory.build(chkRS.getStatus(),
			// chkRS.getErrorMsg());
			// }

			String modelName = null;
			Date nowDate = systemDao.getCurrentDateTime();
			ServEntity serv = null;
			TaskEntity task = null;

			String orderId = (String) paramMap.get("orderId");
			// 获取工单信息
			OrderEntity order = orderDao.get(orderId);

			def = new DefaultTransactionDefinition();
			def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
			txStatus = txManager.getTransaction(def);

			// 保存操作日志
			OperateLogEntity operateLog = saveOperateLog(modelName, operateAcion, order.getId(), order.getServName(),
					nowDate);

			switch (order.getType()) {
			// 创建型工单
			case DictConstants.ORDER_TYPE_CREATE:
				modelName = OperateDictConstants.MODEL_ORDER;
				// 获取更新工单
				order = buildOrderToUpdate(paramMap);
				updateOrderDetail(order);

				order.setStatus(DictConstants.ORDER_STATUS_EXECUTED);
				orderDao.updateStatusAndMsg(order);

				// 获取服务
				serv = buildServ(order, nowDate);
				saveServDetail(serv);

				task = buildCreateServTask(serv, operateLog);
				break;
			case DictConstants.ORDER_TYPE_SCALE_UP:
				order.setStatus(DictConstants.ORDER_STATUS_EXECUTED);
				orderDao.updateStatusAndMsg(order);

				serv = buildChangedServ(order);
				updateServDetail(serv);

				task = buildScaleUpServTask(serv, operateLog);
				break;
			case DictConstants.ORDER_TYPE_IMAGE_UPDATE:
				order.setStatus(DictConstants.ORDER_STATUS_EXECUTED);
				orderDao.updateStatusAndMsg(order);

				serv = buildChangedServ(order);
				updateServDetail(serv);

				task = buildUpdateImageVersionTask(serv, operateLog);
				break;
			default:
				break;
			}

			// 保存任务
			saveTask(task);
			txManager.commit(txStatus);

			startTask(task);
			return RespJsonFactory.buildOK();
		} catch (Exception e) {
			if (txStatus != null) {
				txManager.rollback(txStatus);
			}
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 构建工单变更后的服务
	 * 
	 * @param changedOrder
	 *            变更工单
	 * @return 服务对象
	 */
	public ServEntity buildChangedServ(OrderEntity changedOrder) {
		ServEntity serv = servDao.getByOrderId(changedOrder.getAssociateOrderId());
		serv.setOrder(changedOrder);
		List<SubServEntity> subServs = serv.getSubServs();
		List<SubOrderEntity> changedSubOrders = changedOrder.getSubOrders();

		for (SubServEntity subServ : subServs) {
			for (SubOrderEntity changedSubOrder : changedSubOrders) {
				if (subServ.getSubOrder().getDefinitionSubServ().getName()
						.equals(changedSubOrder.getDefinitionSubServ().getName())) {
					subServ.setSubOrder(changedSubOrder);
					break;
				}
			}
		}
		return serv;
	}

	/**
	 * 工单删除
	 * 
	 * @param id
	 *            工单编码
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String id) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REMOVE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定的工单
			OrderEntity order = orderDao.getBase(id);

			// 工单删除检查
			CheckResult chkRS = orderCheck.checkRemove(order);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 删除工单信息
			deleteOrderDetail(order);

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_ORDER, operateAcion, order.getId(), order.getServName());

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("工单" + operateAcionText + "异常", e);
			throw new APIException("工单" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 是否自动审批
	 * 
	 * @return
	 */
	public boolean isAutoApprove() {
		boolean autoApprove = getUser().getAutoApprove();
		return autoApprove;
	}

	/**
	 * 保存工单信息(保存工单、子工单、工单和子服务的关系)
	 * 
	 * @param order
	 *            工单对象
	 */
	public void saveOrderDetail(OrderEntity order) {
		orderDao.save(order);
		orderDao.saveRelativeSubOrder(order);
		if (order.getBusinessSubSystem() != null) {
			orderDao.saveRelationshipWithBusinessSubSystem(order);
		}
	}

	/**
	 * 更新服务信息(更新服务、更新子服务)
	 * 
	 * @param serv
	 *            服务对象
	 */
	public void updateServDetail(ServEntity serv) {
		List<SubServEntity> subServs = serv.getSubServs();
		for (SubServEntity subServ : subServs) {
			subServDao.update(subServ);
		}
		servDao.update(serv);
	}

	/**
	 * 获取指定站点下的默认区域
	 * 
	 * @param siteId
	 *            站点编码
	 * @return 区域对象
	 */
	private AreaEntity getDefaultArea(String siteId) {
		// TODO 暂时使用随机的一个可用区域
		List<AreaEntity> areas = areaDao.listName(siteId, true);
		// 随机排序
		Collections.shuffle(areas);
		return areas.get(0);
	}

	/**
	 * 更新工单详细(更新工单、子工单)
	 * 
	 * @param order
	 *            工单对象
	 */
	private void updateOrderDetail(OrderEntity order) {
		orderDao.update(order);

		List<SubOrderEntity> subOrders = order.getSubOrders();
		for (SubOrderEntity subOrder : subOrders) {
			subOrderDao.update(subOrder);
		}
	}

	/**
	 * 删除工单详细(删除工单、子工单、工单和子系统的关系)
	 * 
	 * @param order
	 *            工单对象
	 */
	private void deleteOrderDetail(OrderEntity order) {
		orderDao.remove(order.getId());
		orderDao.removeRelativeSubOrder(order.getId());
		if (order.getBusinessSubSystem() != null) {
			orderDao.removeRelationshipWithBusinessSubSystem(order.getId());
		}
	}

	/**
	 * 保存服务详细（保存服务、子服务、单元并更新端口使用状态）
	 * 
	 * @param serv
	 *            服务对象
	 */
	private void saveServDetail(ServEntity serv) {
		servDao.save(serv);
		servDao.saveRelativeSubServ(serv);
		servDao.saveRelativeSubServUnit(serv);

		List<SubServEntity> subServs = serv.getSubServs();
		for (SubServEntity subServ : subServs) {
			PortEntity port = new PortEntity();
			port.setId(subServ.getPort().getId());
			port.setSubServ(subServ);
			port.setUsed(true);
			portDao.updatePortToUsed(port);
		}
	}

	/**
	 * 构建工单展示
	 * 
	 * @param order
	 *            工单
	 * @param showDetail
	 *            是否展示详情
	 * @return 工单展示
	 */
	private OrderDto buildShowDto(OrderEntity order, boolean showDetail) {
		OrderDto orderDto = new OrderDto();
		orderDto.setId(order.getId());

		DefinitionServEntity dfServ = order.getDefinitionServ();
		orderDto.setServTypeName(dfServ.getName());

		AreaEntity area = order.getArea();
		orderDto.setAreaId(area.getId());
		orderDto.setAreaName(area.getName());

		SiteEntity site = area.getSite();
		orderDto.setSiteId(site.getId());
		orderDto.setSiteName(site.getName());

		BusinessSubSystemEntity subSystem = order.getBusinessSubSystem();
		if (subSystem != null) {
			orderDto.setBusinessSubSystemId(subSystem.getId());
			orderDto.setBusinessSubSystemName(subSystem.getName());

			BusinessSystemEntity system = subSystem.getBusinessSystem();
			orderDto.setBusinessSystemId(system.getId());
			orderDto.setBusinessSystemName(system.getName());
		}

		String servName = getServName(order.getServName(), order.getNo());
		orderDto.setServName(servName);
		orderDto.setOwner(order.getOwner());
		orderDto.setSharding(order.getSharding());
		orderDto.setType(order.getType());

		orderDto.setStatus(order.getStatus());
		orderDto.setStatusText(dictTypeCache.getTextFromCache(DictTypeConstants.ORDER_STATUS, order.getStatus()));

		orderDto.setCreateDateTime(DateUtils.dateTimeToString(order.getCreateDateTime()));
		orderDto.setCreateLoginUserName(order.getCreateUserLoginName());

		List<SubOrderEntity> subOrders = order.getSubOrders();
		List<SubOrderDto> subOrderDtos = new ArrayList<>(subOrders.size());
		orderDto.setSubOrders(subOrderDtos);
		for (SubOrderEntity subOrder : subOrders) {
			SubOrderDto subOrderDto = new SubOrderDto();
			subOrderDtos.add(subOrderDto);
			subOrderDto.setId(subOrder.getId());
			DefinitionSubServEntity dfSubServ = subOrder.getDefinitionSubServ();
			subOrderDto.setType(dfSubServ.getName());

			DefinitionSubServArchEntity arch = subOrder.getDefinitionSubServArch();
			subOrderDto.setArchId(arch.getId());
			subOrderDto.setArchName(arch.getName());

			DefinitionSubServUnitScaleEntity scale = subOrder.getDefinitionSubServUnitScale();
			subOrderDto.setScaleId(scale.getId());
			subOrderDto.setScaleName(scale.getName());

			SubServSoftwareImageEntity image = subOrder.getSubServSoftwareImage();
			String imageName = getSoftwareImageNameAndVersion(image);
			subOrderDto.setSoftwareImageId(image.getId());
			subOrderDto.setSoftwareImageName(imageName);

			subOrderDto.setNetworkBandwidth(subOrder.getNetworkBandwidth());

			subOrderDto.setDataDirType(subOrder.getDataDirDeviceType());
			subOrderDto.setDataDirTypeText(
					dictTypeCache.getTextFromCache(DictTypeConstants.DATA_DIR_TYPE, subOrder.getDataDirDeviceType()));

			subOrderDto.setDataDirSize(subOrder.getDataDirSize());

			subOrderDto.setLogDirType(subOrder.getLogDirDeviceType());
			subOrderDto.setLogDirTypeText(
					dictTypeCache.getTextFromCache(DictTypeConstants.LOG_DIR_TYPE, subOrder.getLogDirDeviceType()));

			subOrderDto.setLogDirSize(subOrder.getLogDirSize());

			subOrderDto.setMixed(subOrder.getMixed());
			subOrderDto.setHighAvailable(subOrder.getHighAvailable());
		}
		return orderDto;
	}

	/**
	 * 从工单集合中获取指定工单对应的关联工单
	 * 
	 * @param orders
	 *            工单集合
	 * @param order
	 *            工单
	 * @return OrderEntity 关联工单
	 */
	private OrderEntity getAssociateOrder(List<OrderEntity> orders, OrderEntity order) {
		for (OrderEntity o : orders) {
			if (StringUtils.isNotBlank(order.getAssociateOrderId())) {
				if (order.getAssociateOrderId().equals(o.getId())) {
					return o;
				}
			}
		}
		return null;
	}

	// private String buildServName(String str) {
	// if (StringUtils.isBlank(str)) {
	// return PrimaryKeyUtils.getRandomCharAndNum(4);
	// }
	// String convert = "";
	// for (int j = 0; j < str.length(); j++) {
	// char word = str.charAt(j);
	// String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
	// if (pinyinArray != null) {
	// convert += pinyinArray[0].charAt(0);
	// } else {
	// convert += word;
	// }
	// }
	// convert += "_" + PrimaryKeyUtils.getRandomCharAndNum(4);
	// return convert;
	// }

	/**
	 * 构建工单对象
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 工单对象
	 */
	private OrderEntity buildOrder(Map<String, Object> paramMap) {
		OrderEntity order = new OrderEntity();
		order.setId(PrimaryKeyUtils.uniqueId());

		// 所属服务定义
		DefinitionServEntity dfServ = new DefinitionServEntity();
		dfServ.setCode((String) paramMap.get("definitionServ"));
		order.setDefinitionServ(dfServ);

		// 所属站点
		String siteId = (String) paramMap.get("site");

		// 获取站点默认区域
		AreaEntity area = getDefaultArea(siteId);
		order.setArea(area);

		if (paramMap.containsKey("tag")) {
			if (StringUtils.isNotBlank("tag")) {
				// 所属业务子系统
				String businessSubSystemId = (String) paramMap.get("tag");
				BusinessSubSystemEntity businessSubSystem = businessSubSystemDao.get(businessSubSystemId);
				order.setBusinessSubSystem(businessSubSystem);
			}
		}

		// 服务名称
		order.setServName(StringUtils.trim((String) paramMap.get("servName")));
		order.setNo(1);
		// 工单类型
		order.setType(DictConstants.ORDER_TYPE_CREATE);
		// 工单状态
		order.setStatus(DictConstants.ORDER_STATUS_UNAPPROVED);
		// 是否为分片结构
		boolean sharding = false;
		if (paramMap.get("sharding") != null) {
			sharding = (Boolean) paramMap.get("sharding");
		}
		order.setSharding(sharding);

		UserEntity user = getUser();
		String username = user.getUsername();
		order.setOwner(username);
		order.setCreateDateTime(systemDao.getCurrentDateTime());
		order.setCreateUserLoginName(username);

		// 子工单信息
		List<SubOrderEntity> subOrders = buildSubOrders(paramMap);
		order.setSubOrders(subOrders);
		return order;
	}

	/**
	 * 构建子工单集合
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 子工单集合
	 */
	@SuppressWarnings("unchecked")
	private List<SubOrderEntity> buildSubOrders(Map<String, Object> paramMap) {
		String dfServCode = (String) paramMap.get("definitionServ");
		// 获取指定服务下的子服务信息
		List<DefinitionSubServEntity> dfSubServs = definitionSubServDao.listByDefinitionServCode(dfServCode);
		List<Map<String, Object>> dfSubServs_input = (List<Map<String, Object>>) paramMap.get("definitionSubServs");
		List<SubOrderEntity> subOrders = new ArrayList<SubOrderEntity>(dfSubServs_input.size());
		for (Map<String, Object> map : dfSubServs_input) {
			for (DefinitionSubServEntity dfSubServ : dfSubServs) {
				if (dfSubServ.getName().equals(map.get("name"))) {
					SubOrderEntity subOrder = new SubOrderEntity();
					subOrders.add(subOrder);
					subOrder.setId(PrimaryKeyUtils.uniqueId());
					subOrder.setDefinitionSubServ(dfSubServ);
					// 架构
					DefinitionSubServArchEntity dfSubServArch = dfSubServ.getDefaultDefinitionSubServArch();
					// 规模
					DefinitionSubServUnitScaleEntity dfSubServUnitScale = dfSubServ
							.getDefaultDefinitionSubServUnitScale();
					// 软件版本
					SubServSoftwareImageEntity subServSoftwareImage = null;
					String siteId = (String) paramMap.get("site");
					List<SubServSoftwareImageEntity> subServSoftwareImages = subServSoftwareImageDao
							.listSubServSoftwareImageVersion(siteId, dfSubServ.getName(), true);
					subServSoftwareImage = subServSoftwareImages.get(0);
					// 带宽
					Integer networkBandWidth = 0;
					// 数据目录设备类型
					String dataDirDeviceType = dfSubServ.getDefaultDataDirDeviceType();
					// 数据目录大小
					Long dataDirSize = dfSubServ.getDefaultDataDirSize();
					// 日志目录设备类型
					String logDirDeviceType = dfSubServ.getDefaultLogDirDeviceType();
					// 日志目录大小
					Long logDirSize = dfSubServ.getDefaultLogDirSize();
					// 混合部署
					Boolean mixed = false;
					Boolean highAvailable = false;
					if (map.containsKey("arch")) {
						dfSubServArch = new DefinitionSubServArchEntity();
						dfSubServArch.setId((String) map.get("arch"));
					}

					if (map.containsKey("scale")) {
						dfSubServUnitScale = new DefinitionSubServUnitScaleEntity();
						dfSubServUnitScale.setId((String) map.get("scale"));
					}

					if (map.containsKey("softwareImage")) {
						String subServSoftwareImageId = (String) map.get("softwareImage");
						subServSoftwareImage = new SubServSoftwareImageEntity();
						subServSoftwareImage.setId(subServSoftwareImageId);
					}

					if (map.containsKey("networkBandwidth")) {
						networkBandWidth = (Integer) map.get("networkBandwidth");
					}

					if (map.containsKey("dataDirDeviceType")) {
						dataDirDeviceType = (String) map.get("dataDirDeviceType");
					}

					if (map.containsKey("dataDirSize")) {
						dataDirSize = (Long) map.get("dataDirSize");
					}

					if (map.containsKey("mixed")) {
						mixed = (Boolean) map.get("mixed");
					}

					if (map.containsKey("highAvailable")) {
						highAvailable = (Boolean) map.get("highAvailable");
					}

					subOrder.setDefinitionSubServArch(dfSubServArch);
					subOrder.setDefinitionSubServUnitScale(dfSubServUnitScale);
					subOrder.setSubServSoftwareImage(subServSoftwareImage);
					subOrder.setNetworkBandwidth(networkBandWidth);
					subOrder.setDataDirDeviceType(dataDirDeviceType);
					subOrder.setDataDirSize(dataDirSize);
					subOrder.setLogDirDeviceType(logDirDeviceType);
					subOrder.setLogDirSize(logDirSize);
					subOrder.setMixed(mixed);
					subOrder.setHighAvailable(highAvailable);
					break;
				}
			}
		}
		return subOrders;
	}

	/**
	 * 构建工单对象用于更新
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return 工单对象
	 */
	@SuppressWarnings("unchecked")
	private OrderEntity buildOrderToUpdate(Map<String, Object> paramMap) {
		String orderId = (String) paramMap.get("orderId");
		// 获取工单信息
		OrderEntity order = orderDao.get(orderId);

		// 所属站点
		if (paramMap.containsKey("site")) {
			String siteId = (String) paramMap.get("site");
			if (!order.getArea().getSite().getId().equals(siteId)) {
				AreaEntity area = getDefaultArea(siteId);
				order.setArea(area);
			}
		}

		// 所属区域
		if (paramMap.containsKey("area")) {
			String areaId = (String) paramMap.get("area");
			if (!order.getArea().getId().equals(areaId)) {
				AreaEntity area = areaDao.get(areaId);
				order.setArea(area);
			}
		}

		// 分片结构
		if (paramMap.containsKey("sharding")) {
			order.setSharding((Boolean) paramMap.get("sharding"));
		}

		// // 所属业务子系统
		// if (paramMap.containsKey("tag")) {
		// if (StringUtils.isNotBlank("tag")) {
		// // 所属业务子系统
		// String businessSubSystemId = (String) paramMap.get("tag");
		// BusinessSubSystemEntity businessSubSystem =
		// businessSubSystemDao.get(businessSubSystemId);
		// order.setBusinessSubSystem(businessSubSystem);
		// }
		// }

		//
		List<Map<String, Object>> dfSubServs = (List<Map<String, Object>>) paramMap.get("definitionSubServs");
		if (dfSubServs != null) {
			List<SubOrderEntity> subOrders = order.getSubOrders();
			for (Map<String, Object> map : dfSubServs) {
				for (SubOrderEntity subOrder : subOrders) {
					DefinitionSubServEntity dfSubServ = subOrder.getDefinitionSubServ();
					if (dfSubServ.getName().equals(map.get("name"))) {
						// 架构
						if (map.containsKey("arch")) {
							DefinitionSubServArchEntity dfSubServArch = new DefinitionSubServArchEntity();
							dfSubServArch.setId((String) map.get("arch"));
							subOrder.setDefinitionSubServArch(dfSubServArch);
						}

						// 规模
						if (map.containsKey("scale")) {
							DefinitionSubServUnitScaleEntity dfSubServUnitScale = new DefinitionSubServUnitScaleEntity();
							dfSubServUnitScale.setId((String) map.get("scale"));
							subOrder.setDefinitionSubServUnitScale(dfSubServUnitScale);
						}

						// 软件版本
						if (map.containsKey("softwareImage")) {
							SubServSoftwareImageEntity subServSoftwareImage = new SubServSoftwareImageEntity();
							subServSoftwareImage.setId((String) map.get("softwareImage"));
							subOrder.setSubServSoftwareImage(subServSoftwareImage);
						}

						// 网络带宽
						if (map.containsKey("networkBandwidth")) {
							Integer networkBandWidth = (Integer) map.get("networkBandwidth");
							subOrder.setNetworkBandwidth(networkBandWidth);
						}

						// 数据目录设备类型
						if (map.containsKey("dataDirDeviceType")) {
							subOrder.setDataDirDeviceType((String) map.get("dataDirDeviceType"));
						}

						// 数据目录大小
						if (map.containsKey("dataDirSize")) {
							subOrder.setDataDirSize((Long) map.get("dataDirSize"));
						}

						// 日志目录设备类型
						if (map.containsKey("logDirDeviceType")) {
							subOrder.setLogDirDeviceType((String) map.get("logDirDeviceType"));
						}

						// 日志目录大小
						if (map.containsKey("logDirSize")) {
							subOrder.setLogDirSize((Long) map.get("logDirSize"));
						}

						if (map.containsKey("mixed")) {
							subOrder.setMixed((Boolean) map.get("mixed"));
						}

						if (map.containsKey("highAvailable")) {
							subOrder.setHighAvailable((Boolean) map.get("highAvailable"));
						}
						break;
					}
				}
			}

		}
		return order;
	}

	/**
	 * 构建服务对象
	 * 
	 * @param order
	 *            工单对象
	 * @param nowDate
	 *            时间
	 * @return 服务对象
	 */
	private ServEntity buildServ(OrderEntity order, Date nowDate) {
		ServEntity serv = new ServEntity();
		serv.setId(PrimaryKeyUtils.uniqueId());
		serv.setOrder(order);
		serv.setServName(getServName(order.getServName(), order.getNo()));
		serv.setCreateDateTime(nowDate);
		UserEntity user = getUser();
		String username = user.getUsername();
		serv.setCreateUserLoginName(username);

		// 获取未使用的端口集合
		List<PortEntity> unusedPorts = portDao.listUnused(order.getArea().getSite().getId());
		List<SubOrderEntity> subOrders = order.getSubOrders();
		List<SubServEntity> subServs = new ArrayList<SubServEntity>(subOrders.size());
		for (int i = 0; i < subOrders.size(); i++) {
			SubOrderEntity subOrder = subOrders.get(i);
			SubServEntity subServ = new SubServEntity();
			subServ.setId(PrimaryKeyUtils.uniqueId());
			subServ.setSubOrder(subOrder);

			PortEntity unusedPort = unusedPorts.get(i);
			subServ.setPort(unusedPort);

			// 子服务单元
			int unitNum = subOrder.getDefinitionSubServArch().getUnitNum();
			List<UnitEntity> units = new ArrayList<UnitEntity>(unitNum);
			for (int j = 0; j < unitNum; j++) {
				UnitEntity unit = new UnitEntity();
				unit.setId(PrimaryKeyUtils.uniqueId());
				units.add(unit);
			}
			subServ.setUnits(units);
			subServs.add(subServ);
		}
		serv.setSubServs(subServs);
		return serv;
	}

	/**
	 * 构建服务创建任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	private TaskEntity buildCreateServTask(ServEntity serv, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(serv.getOrder().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_SERV);
		task.setObjId(serv.getId());
		task.setObjName(serv.getServName());
		task.setObj(serv);
		task.setActionType(TaskDictConstants.ACTION_TYPE_CREATE);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(serv.getOrder().getOwner());
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_CREATE_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildCreateServSubTasks(serv, task.getStartDateTime());
		task.setSubTasks(subTasks);
		return task;
	}

	/**
	 * 构建服务创建子任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	private List<SubTaskEntity> buildCreateServSubTasks(ServEntity serv, Date date) {
		return buildCreateServSubTasks(serv, date, 1);
	}

	/**
	 * 构建服务创建子任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param date
	 *            任务开始时间
	 * @param startPriority
	 *            优先级
	 * @return 子任务集合
	 */
	public List<SubTaskEntity> buildCreateServSubTasks(ServEntity serv, Date date, int startPriority) {
		List<SubServEntity> subServs = serv.getSubServs();
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>();

		sortByPriorityASC(subServs);
		for (SubServEntity subServ : subServs) {
			SubTaskEntity subTask = new SubTaskEntity();
			subTasks.add(subTask);

			subTask.setId(PrimaryKeyUtils.uniqueId());
			subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_SUBSERV);
			subTask.setObjId(subServ.getId());
			subTask.setObjName(subServ.getSubOrder().getDefinitionSubServ().getName());
			subTask.setObj(subServ);
			subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_CREATE);
			subTask.setAsync(true);
			DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache
					.getDfSubTaskConfigFromCache(subTask.getObjType(), subTask.getActionType());
			if (dfSubTaskConfig == null) {
				subTask.setTimeout(0);
			} else {
				subTask.setTimeout(dfSubTaskConfig.getTimeout());
			}
			if (startPriority == 1) {
				subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
				subTask.setStartDateTime(date);
			} else {
				subTask.setStatus(SubTaskDictConstants.STATUS_NOTRUN);
			}
			String url = "/" + SysConstants.MGM_VERSION + "/services?compose="
					+ subServ.getSubOrder().getDefinitionSubServ().getCompose();
			subTask.setUrl(url);
			subTask.setMethodType(HttpClientUtils.METHOD_POST);
			String subTaskParam = buildParamForCreateSubServ(subServ, serv);
			subTask.setParam(subTaskParam);
			subTask.setPriority(startPriority);
			startPriority++;
		}

		String defitionServCode = serv.getOrder().getDefinitionServ().getCode();
		if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(defitionServCode)
				|| SysConstants.SERV_UPREDIS_URPROXY_SENTINEL_CODE.equals(defitionServCode)) {
			SubTaskEntity subTask_link = new SubTaskEntity();
			subTasks.add(subTask_link);

			subTask_link.setId(PrimaryKeyUtils.uniqueId());
			subTask_link.setObjType(SubTaskDictConstants.OBJ_TYPE_SUBSERV);
			subTask_link.setObjId(serv.getId());
			subTask_link.setObjName(serv.getServName());
			subTask_link.setObj(null);
			subTask_link.setActionType(SubTaskDictConstants.ACTION_TYPE_LINK);
			subTask_link.setAsync(true);
			DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache.getDfSubTaskConfigFromCache(
					SubTaskDictConstants.OBJ_TYPE_SUBSERV, SubTaskDictConstants.ACTION_TYPE_LINK);
			if (dfSubTaskConfig == null) {
				subTask_link.setTimeout(0);
			} else {
				subTask_link.setTimeout(dfSubTaskConfig.getTimeout());
			}
			if (startPriority == 1) {
				subTask_link.setStatus(SubTaskDictConstants.STATUS_RUNNING);
				subTask_link.setStartDateTime(date);
			} else {
				subTask_link.setStatus(SubTaskDictConstants.STATUS_NOTRUN);
			}
			String url = "/" + SysConstants.MGM_VERSION + "/services/link";
			subTask_link.setUrl(url);
			subTask_link.setMethodType(HttpClientUtils.METHOD_POST);
			subTask_link.setParam("dynamic");
			subTask_link.setPriority(startPriority);
			startPriority++;
		}

		return subTasks;
	}

	/**
	 * 构建服务扩容任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	public TaskEntity buildScaleUpServTask(ServEntity serv, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(serv.getOrder().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_SERV);
		task.setObjId(serv.getId());
		task.setObjName(serv.getServName());
		task.setObj(serv);
		task.setActionType(TaskDictConstants.ACTION_TYPE_SCALE_UP);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(serv.getOrder().getOwner());
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_SCALE_UP_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildScaleUpServSubTasks(serv, task.getStartDateTime());
		task.setSubTasks(subTasks);
		return task;
	}

	/**
	 * 构建服务扩容子任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	public List<SubTaskEntity> buildScaleUpServSubTasks(ServEntity serv, Date date) {
		List<SubServEntity> subServs = serv.getSubServs();
		OrderEntity order = serv.getOrder();

		// 关联工单
		OrderEntity associateOrder = orderDao.get(order.getAssociateOrderId());

		List<String> changedSubServType = new ArrayList<>();
		List<SubOrderEntity> subOrders = order.getSubOrders();
		List<SubOrderEntity> associateSubOrders = associateOrder.getSubOrders();
		for (SubOrderEntity subOrder : subOrders) {
			String subServType = subOrder.getDefinitionSubServ().getName();
			for (SubOrderEntity associateSubOrder : associateSubOrders) {
				if (subServType.equals(associateSubOrder.getDefinitionSubServ().getName())) {
					if (!subOrder.getDefinitionSubServUnitScale().getId()
							.equals(associateSubOrder.getDefinitionSubServUnitScale().getId())
							|| !subOrder.getDataDirSize().equals(associateSubOrder.getDataDirSize())
							|| !subOrder.getNetworkBandwidth().equals(associateSubOrder.getNetworkBandwidth())) {
						if (!changedSubServType.contains(subServType)) {
							changedSubServType.add(subServType);
						}
					}
					break;
				}
			}
		}

		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>();

		sortByPriorityASC(subServs);
		int priority = 1;

		for (SubServEntity subServ : subServs) {
			String subServType = subServ.getSubOrder().getDefinitionSubServ().getName();
			if (changedSubServType.contains(subServType)) {
				SubTaskEntity subTask = new SubTaskEntity();
				subTasks.add(subTask);

				subTask.setId(PrimaryKeyUtils.uniqueId());
				subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_SUBSERV);
				subTask.setObjId(subServ.getId());
				subTask.setObjName(subServType);
				subTask.setObj(subServ);
				subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_SCALE_UP);
				subTask.setAsync(true);
				DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache
						.getDfSubTaskConfigFromCache(subTask.getObjType(), subTask.getActionType());
				if (dfSubTaskConfig == null) {
					subTask.setTimeout(0);
				} else {
					subTask.setTimeout(dfSubTaskConfig.getTimeout());
				}
				if (priority == 1) {
					subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
					subTask.setStartDateTime(date);
				} else {
					subTask.setStatus(SubTaskDictConstants.STATUS_NOTRUN);
				}
				String url = "/" + SysConstants.MGM_VERSION + "/services/" + subServ.getRelateId() + "/update";
				subTask.setUrl(url);
				subTask.setMethodType(HttpClientUtils.METHOD_POST);
				String subTaskParam = buildScaleUpSubServParam(subServ);
				subTask.setParam(subTaskParam);
				subTask.setPriority(priority);
				priority++;
			}
		}
		return subTasks;
	}

	/**
	 * 构建子服务扩容所需参数
	 * 
	 * @param subServ
	 *            子服务对象
	 * @return String 子服务扩容所需参数
	 */
	private String buildScaleUpSubServParam(SubServEntity subServ) {
		JSONObject paramInfo = new JSONObject();
		// 规模
		DefinitionSubServUnitScaleEntity scale = subServ.getSubOrder().getDefinitionSubServUnitScale();
		JSONObject requireInfo = new JSONObject();
		paramInfo.put("require", requireInfo);
		requireInfo.put("ncpu", scale.getCpuNum());
		requireInfo.put("memory", scale.getMemSize());

		JSONArray volumesInfo = new JSONArray();
		paramInfo.put("volumes", volumesInfo);

		JSONObject volume_dataInfo = new JSONObject();
		volumesInfo.add(volume_dataInfo);
		volume_dataInfo.put("name", "DAT");
		volume_dataInfo.put("size", subServ.getSubOrder().getDataDirSize());

		JSONArray networksInfo = new JSONArray();
		paramInfo.put("networks", networksInfo);
		JSONObject networkInfo = new JSONObject();
		int bandwidth = subServ.getSubOrder().getNetworkBandwidth();
		networkInfo.put("bandwidth", bandwidth);
		networksInfo.add(networkInfo);

		return paramInfo.toJSONString();
	}

	/**
	 * 构建服务镜像版本变更任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param operateLog
	 *            操作日志对象
	 * @return 任务对象
	 */
	public TaskEntity buildUpdateImageVersionTask(ServEntity serv, OperateLogEntity operateLog) {
		TaskEntity task = new TaskEntity();
		task.setId(PrimaryKeyUtils.uniqueId());
		task.setSite(serv.getOrder().getArea().getSite());
		task.setObjType(TaskDictConstants.OBJ_TYPE_SERV);
		task.setObjId(serv.getId());
		task.setObjName(serv.getServName());
		task.setObj(serv);
		task.setActionType(TaskDictConstants.ACTION_TYPE_IMAGE_UPDATE);
		task.setOperateLog(operateLog);
		UserEntity user = getUser();
		String username = user.getUsername();
		task.setOwner(serv.getOrder().getOwner());
		task.setCreateUserLoginName(username);
		task.setStatus(TaskDictConstants.STATUS_IMAGE_UPDATE_RUNNING);
		task.setStartDateTime(operateLog.getCreateDateTime());

		List<SubTaskEntity> subTasks = buildUpdateImageVersionSubTasks(serv, task.getStartDateTime());
		task.setSubTasks(subTasks);
		return task;
	}

	/**
	 * 构建服务镜像版本变更子任务
	 * 
	 * @param serv
	 *            服务对象
	 * @param date
	 *            任务开始时间
	 * @return 子任务集合
	 */
	public List<SubTaskEntity> buildUpdateImageVersionSubTasks(ServEntity serv, Date date) {
		List<SubServEntity> subServs = serv.getSubServs();
		List<SubTaskEntity> subTasks = new ArrayList<SubTaskEntity>();

		OrderEntity order = serv.getOrder();

		// 关联工单
		OrderEntity associateOrder = orderDao.get(order.getAssociateOrderId());

		List<String> changedSubServType = new ArrayList<>();
		List<SubOrderEntity> subOrders = order.getSubOrders();
		List<SubOrderEntity> associateSubOrders = associateOrder.getSubOrders();
		for (SubOrderEntity subOrder : subOrders) {
			String subServType = subOrder.getDefinitionSubServ().getName();
			for (SubOrderEntity associateSubOrder : associateSubOrders) {
				if (subServType.equals(associateSubOrder.getDefinitionSubServ().getName())) {
					if (!subOrder.getSubServSoftwareImage().getId()
							.equals(associateSubOrder.getSubServSoftwareImage().getId())) {
						if (!changedSubServType.contains(subServType)) {
							changedSubServType.add(subServType);
						}
					}
					break;
				}
			}
		}

		sortByPriorityASC(subServs);
		int priority = 1;

		for (SubServEntity subServ : subServs) {
			String subServType = subServ.getSubOrder().getDefinitionSubServ().getName();
			if (changedSubServType.contains(subServType)) {
				SubTaskEntity subTask = new SubTaskEntity();
				subTasks.add(subTask);

				subTask.setId(PrimaryKeyUtils.uniqueId());
				subTask.setObjType(SubTaskDictConstants.OBJ_TYPE_SUBSERV);
				subTask.setObjId(subServ.getId());
				subTask.setObjName(subServType);
				subTask.setObj(subServ);
				subTask.setActionType(SubTaskDictConstants.ACTION_TYPE_IMAGE_UPDATE);
				subTask.setAsync(true);
				DefinitionSubTaskConfigEntity dfSubTaskConfig = definitionSubTaskConfigCache
						.getDfSubTaskConfigFromCache(subTask.getObjType(), subTask.getActionType());
				if (dfSubTaskConfig == null) {
					subTask.setTimeout(0);
				} else {
					subTask.setTimeout(dfSubTaskConfig.getTimeout());
				}
				if (priority == 1) {
					subTask.setStatus(SubTaskDictConstants.STATUS_RUNNING);
					subTask.setStartDateTime(date);
				} else {
					subTask.setStatus(SubTaskDictConstants.STATUS_NOTRUN);
				}
				String url = "/" + SysConstants.MGM_VERSION + "/services/" + subServ.getRelateId()
						+ "/image/update?image=" + subServ.getSubOrder().getSubServSoftwareImage().getRelateId();
				subTask.setUrl(url);
				subTask.setMethodType(HttpClientUtils.METHOD_POST);
				subTask.setParam(null);
				subTask.setPriority(priority);
				priority++;
			}
		}
		return subTasks;
	}

	/**
	 * 构建子服务创建所需参数
	 * 
	 * @param subServ
	 *            子服务对象
	 * @param serv
	 *            服务对象
	 * @return String 子服务创建所需参数
	 */
	private String buildParamForCreateSubServ(SubServEntity subServ, ServEntity serv) {
		JSONObject paramJson = new JSONObject();
		SubOrderEntity subOrder = subServ.getSubOrder();
		DefinitionSubServEntity dfSubServ = subOrder.getDefinitionSubServ();
		paramJson.put("name", subServ.getId());
		paramJson.put("high_available", subServ.getSubOrder().getHighAvailable());

		JSONObject imageJson = new JSONObject();
		paramJson.put("image", imageJson);
		imageJson.put("id", subOrder.getSubServSoftwareImage().getRelateId());

		DefinitionSubServArchEntity dfSubServArch = subOrder.getDefinitionSubServArch();
		DefinitionSubServUnitScaleEntity dfSubServUnitScale = subOrder.getDefinitionSubServUnitScale();
		paramJson.put("tag", serv.getServName());

		JSONObject architectureJson = new JSONObject();
		paramJson.put("architecture", architectureJson);
		architectureJson.put("mode", dfSubServArch.getType());
		architectureJson.put("code", dfSubServArch.getCode());
		architectureJson.put("unit_num", dfSubServArch.getUnitNum());

		JSONObject unitRequireJson = new JSONObject();
		paramJson.put("unit_require", unitRequireJson);

		JSONObject requireJson = new JSONObject();
		unitRequireJson.put("require", requireJson);
		requireJson.put("ncpu", dfSubServUnitScale.getCpuNum());
		requireJson.put("memory", dfSubServUnitScale.getMemSize());

		JSONArray volumesJsonArray = new JSONArray();
		unitRequireJson.put("volumes", volumesJsonArray);

		JSONObject volumeJson_data = new JSONObject();
		volumesJsonArray.add(volumeJson_data);
		volumeJson_data.put("name", "DAT");
		volumeJson_data.put("type", definitionCache.getDefinitionCodeFromCache(DictTypeConstants.DATA_DIR_TYPE,
				subOrder.getDataDirDeviceType()));
		volumeJson_data.put("size", subOrder.getDataDirSize());

		JSONObject volumeJson_log = new JSONObject();
		volumesJsonArray.add(volumeJson_log);
		volumeJson_log.put("name", "LOG");
		volumeJson_log.put("type", definitionCache.getDefinitionCodeFromCache(DictTypeConstants.LOG_DIR_TYPE,
				subOrder.getLogDirDeviceType()));
		volumeJson_log.put("size", subOrder.getLogDirSize());

		JSONObject volumeJson_nfs = new JSONObject();
		volumeJson_nfs.put("type", "NFS");
		volumesJsonArray.add(volumeJson_nfs);

		JSONArray networksJsonArray = new JSONArray();
		unitRequireJson.put("networks", networksJsonArray);
		JSONObject networkJson = new JSONObject();
		int bandwidth = subOrder.getNetworkBandwidth();
		networkJson.put("bandwidth", bandwidth);
		networksJsonArray.add(networkJson);

		String areaId = serv.getOrder().getArea().getId();
		// 获取区域下的所有可用的指定集群
		List<ClusterEntity> areaClusters = clusterDao.listByAreaIdAndMixedAndEnabled(areaId,
				subServ.getSubOrder().getMixed(), true);
		// 包含指定软件的集群
		List<ClusterEntity> clusters = new ArrayList<ClusterEntity>();
		for (ClusterEntity cluster : areaClusters) {
			String definitionSubServNames = cluster.getDefinitionSubServNames();
			String[] dfSubServNameArr = definitionSubServNames.split(",");
			for (String dfSubServName : dfSubServNameArr) {
				if (dfSubServName.equals(dfSubServ.getName())) {
					clusters.add(cluster);
					break;
				}
			}
		}

		String[] clusterIdArr = new String[clusters.size()];
		Map<String, String[]> networkingMap = new HashMap<>();
		for (int i = 0; i < clusters.size(); i++) {
			ClusterEntity cluster = clusters.get(i);
			clusterIdArr[i] = cluster.getRelateId();

			List<NetworkingEntity> networkings = cluster.getNetworkings();
			String[] networkingIdArr = new String[networkings.size()];
			for (int j = 0; j < networkings.size(); j++) {
				NetworkingEntity networking = networkings.get(j);
				networkingIdArr[j] = networking.getId();
			}
			networkingMap.put(cluster.getRelateId(), networkingIdArr);
		}
		paramJson.put("cluster_id", clusterIdArr);
		paramJson.put("networking", networkingMap);

		JSONObject optsJson = new JSONObject();
		paramJson.put("opts", optsJson);
		optsJson.put("mysqld::character_set_server", "utf8");
		optsJson.put(dfSubServ.getPortKey(), subServ.getPort().getPortValue());

		return paramJson.toJSONString();
	}

	private String getServName(String orderServName, Integer orderNo) {
		String servName = orderServName;
		if (orderNo != null) {
			servName += String.format("%03d", orderNo);
		}
		return servName;
	}

}
